let s:suite = themis#suite('visual_emulation')
let s:assert = themis#helper('assert')

" Helper:
function! s:add_line(str)
    put! =a:str
endfunction
function! s:add_lines(lines)
    for line in reverse(a:lines)
        put! =line
    endfor
endfunction
function! s:get_pos_char()
    return getline('.')[col('.')-1]
endfunction

function! s:reset_buffer()
    normal! ggdG
    call s:add_lines(['1pattern_a', '2pattern_b', '3pattern_c', '4pattern_d', '5pattern_e'])
    normal! G
    call s:add_lines(range(100))
    normal! Gddgg0zt
endfunction

function! s:suite.before_each()
    call s:reset_buffer()
endfunction

function! s:assert.equal_matches(pattern, ...)
    " :h getmatches()
    let m = getmatches()[0]
    call s:assert.equals(m.pattern, a:pattern)
endfunction

function! s:assert.equal_view(view)
    for key in keys(a:view)
        call s:assert.equals(winsaveview()[key], a:view[key])
    endfor
endfunction

function! s:assert.equal_line(line)
    call s:assert.equals(getline('.'), a:line)
endfunction

function! s:assert.equal_pos_char(char)
    call s:assert.equals(s:get_pos_char(), a:char)
endfunction

function! s:suite.emulate_v()
    normal! v3jy
    call s:assert.equals(visualmode(), "v")
    call incsearch#highlight#emulate_visual_highlight()
    call s:assert.equal_matches('\v%1l%1c\_.{-}%4l|%4l\_.*%4l%1c')
    call incsearch#highlight#emulate_visual_highlight('v')
    call s:assert.equal_matches('\v%1l%1c\_.{-}%4l|%4l\_.*%4l%1c')
endfunction

function! s:suite.emulate_V()
    normal! V3jy
    call s:assert.equals(visualmode(), "V")
    call incsearch#highlight#emulate_visual_highlight()
    call s:assert.equal_matches('\v%1l\_.*%4l')
    call incsearch#highlight#emulate_visual_highlight('V')
    call s:assert.equal_matches('\v%1l\_.*%4l')
endfunction

function! s:suite.emulate_ctrl_v()
    exec "normal! \<C-v>2j2ly"
    call s:assert.equals(visualmode(), "\<C-v>")
    call incsearch#highlight#emulate_visual_highlight()
    call s:assert.equal_matches('\v%1l%1c.*%4c|%2l%1c.*%4c|%3l%1c.*%4c')
    call incsearch#highlight#emulate_visual_highlight("\<C-v>")
    call s:assert.equal_matches('\v%1l%1c.*%4c|%2l%1c.*%4c|%3l%1c.*%4c')
endfunction

function! s:suite.emulate_v_End()
    normal! v3j$y
    call s:assert.equals(visualmode(), 'v')
    call incsearch#highlight#emulate_visual_highlight()
    call s:assert.equal_matches('\v%1l%1c\_.{-}%4l|%4l\_.*%4l%11c')
    call incsearch#highlight#emulate_visual_highlight('v')
    call s:assert.equal_matches('\v%1l%1c\_.{-}%4l|%4l\_.*%4l%11c')
endfunction

function! s:suite.emulate_V_End()
    normal! V3j$y
    call s:assert.equals(visualmode(), 'V')
    call incsearch#highlight#emulate_visual_highlight()
    call s:assert.equal_matches('\v%1l\_.*%4l')
    call incsearch#highlight#emulate_visual_highlight('V')
    call s:assert.equal_matches('\v%1l\_.*%4l')
endfunction

function! s:suite.emulate_ctrl_v_End()
    exec "normal! \<C-v>3j$y"
    call s:assert.equals(visualmode(), "\<C-v>")
    call incsearch#highlight#emulate_visual_highlight()
    call s:assert.equal_matches('\v%1l%1c.*%11c|%2l%1c.*%11c|%3l%1c.*%11c|%4l%1c.*%11c')
    call incsearch#highlight#emulate_visual_highlight("\<C-v>")
    call s:assert.equal_matches('\v%1l%1c.*%11c|%2l%1c.*%11c|%3l%1c.*%11c|%4l%1c.*%11c')
endfunction

function! s:suite.custom_highlight()
    normal! v3jy
    call s:assert.equals(visualmode(), 'v')
    call incsearch#highlight#emulate_visual_highlight()
    let visual_hl = incsearch#highlight#capture('Visual')
    call s:assert.equals(getmatches()[0].group, '_IncSearchVisual')
    let h = incsearch#highlight#capture('_IncSearchVisual')
    call s:assert.equals(h.highlight, visual_hl.highlight)

    let error_hl = incsearch#highlight#capture('ErrorMsg')
    call incsearch#highlight#emulate_visual_highlight('v', error_hl)
    let h = incsearch#highlight#capture('_IncSearchVisual')
    call s:assert.equals(h.highlight, error_hl.highlight)
endfunction

function! s:suite.get_pattern_v()
    let r = incsearch#highlight#get_visual_pattern('v', [5,2], [2,4])
    call s:assert.equals(r, '\v%2l%4c\_.{-}%5l|%5l\_.*%5l%2c')
endfunction

function! s:suite.get_pattern_V()
    let r = incsearch#highlight#get_visual_pattern('V', [5,2], [2,4])
    call s:assert.equals(r, '\v%2l\_.*%5l')
endfunction

function! s:suite.get_pattern_ctrl_v()
    let r = incsearch#highlight#get_visual_pattern("\<C-v>", [5,2], [2,4])
    call s:assert.equals(r, '\v%2l%2c.*%5c|%3l%2c.*%5c|%4l%2c.*%5c|%5l%2c.*%5c')
endfunction

function! s:suite.over_win_height()
    normal! 100ggzz
    let r = incsearch#highlight#get_visual_pattern('V', [1,1], [100,100])
    let e = incsearch#highlight#get_visual_pattern('V', [line('w0'),1], [100,100])
    call s:assert.equals(r, e)
    normal! ggzt
    let r2 = incsearch#highlight#get_visual_pattern('V', [1,1], [100,100])
    let e2 = '\v%1l\_.*%' . line('w$') . 'l'
    call s:assert.equals(r2, e2)
endfunction

function! s:suite.unexpected_mode()
    let throwed = 0
    try
        let r = incsearch#highlight#get_visual_pattern('a', [1,1], [100,100])
    catch /incsearch.vim:/
        let throwed = 1
        call s:assert.equals(v:exception, 'incsearch.vim: unexpected mode a')
    endtry
    call s:assert.equals(throwed, 1)
endfunction

function! s:suite.update_highlight_on_colorscheme()
    colorscheme default
    let old_hl = incsearch#highlight#get_visual_hlobj()
    colorscheme desert
    let new_hl = incsearch#highlight#get_visual_hlobj()
    call s:assert.not_equals(old_hl, new_hl)
endfunction

